package ihm.panel.camera.streaming;

import ihm.dialog.WaitDialog;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import org.hibernate.Session;
import org.hibernate.Transaction;

import bdd.sql.server.bean.ServerAuth;
import bdd.sql.server.bean.ServerCentral;
import bdd.sql.server.bean.ServerWeb;
import bdd.sql.server.bean.Video;
import bdd.sql.server.hibernate.HibernateUtil;

import network.KrakenClient;
import network.messages.KrakenClientMsg;
import network.messages.KrakenServerMsg;
import network.ssl.KrakenSSLClient;
import network.thread.NetworkThread;
import tools.StringUtils;

public class StreamPlayerPanel extends JPanel implements ActionListener {

	private static final long serialVersionUID = 1L;

	// network
	// TODO aller chercher les ips en base
	private boolean authenticated = false;
	private String ip_central = "";
	private String ip_auth = "";
	private String ip_site = "";
	private String ip_web = "";
	private String ip_cam = "";

	private KrakenSSLClient cmd_client;
	private KrakenSSLClient vid_client;

	private Thread cmd_thread;
	private Thread vid_thread;
	
	private int REQUEST_TYPE = 0;

	// GUI
	private StreamPanel display_panel;

	private JPanel stats_panel;
	private JLabel fps_label;
	private JLabel fps_count_label;
	private JLabel latency_label;
	private JLabel latency_count_label;

	private JPanel control_panel;
	private JButton stopButton;
	private JButton pauseButton;
	private JButton playButton;
	private JButton connectButton;

	private Thread display_thread;

	public StreamPlayerPanel() {
		setLayout(new BorderLayout());

		// control_panel
		stopButton = new JButton();
		stopButton.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/control_stop_blue.png")));
		stopButton.setToolTipText("Stop");
		stopButton.setEnabled(false);
		stopButton.addActionListener(this);

		pauseButton = new JButton();
		pauseButton.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/control_pause_blue.png")));
		pauseButton.setToolTipText("Pause");
		pauseButton.setEnabled(false);
		pauseButton.addActionListener(this);

		playButton = new JButton();
		playButton.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/control_play_blue.png")));
		playButton.setToolTipText("Play");
		playButton.setEnabled(false);
		playButton.addActionListener(this);

		connectButton = new JButton();
		connectButton.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/connect.png")));
		connectButton.setToolTipText("Connect");
		connectButton.addActionListener(this);

		control_panel = new JPanel();
		control_panel.add(stopButton);
		control_panel.add(pauseButton);
		control_panel.add(playButton);
		control_panel.add(connectButton);

		// stats_panel
		fps_label = new JLabel("FPS");
		fps_count_label = new JLabel("0");
		latency_label = new JLabel("Latence");
		latency_count_label = new JLabel("0 ms");

		stats_panel = new JPanel();
		GridBagConstraints c = new GridBagConstraints();
		stats_panel.setLayout(new GridBagLayout());
		c.insets = new Insets(3, 3, 3, 3);

		c.gridx = 0;						// position en x
		c.gridy = 0;						// position en y
		c.gridwidth = 1;					// largeur de l'object en nombre de case, ici le reste de la ligne
		c.anchor = GridBagConstraints.WEST;	// l'ancrage de l'object
		c.fill = GridBagConstraints.NONE;	// est ce que l'object prend toute la case?
		stats_panel.add(fps_label, c);

		c.gridx = 1;
		c.gridy = 0;
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.anchor = GridBagConstraints.WEST;
		c.fill = GridBagConstraints.NONE;
		stats_panel.add(fps_count_label, c);

		c.gridx = 0;
		c.gridy = 1;
		c.gridwidth = 1;
		c.anchor = GridBagConstraints.WEST;
		c.fill = GridBagConstraints.NONE;
		stats_panel.add(latency_label, c);

		c.gridx = 1;
		c.gridy = 1;
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.anchor = GridBagConstraints.WEST;
		c.fill = GridBagConstraints.NONE;
		stats_panel.add(latency_count_label, c);

		// display_panel
		display_panel = new StreamPanel(this);

		add(BorderLayout.CENTER, display_panel);
		add(BorderLayout.EAST, stats_panel);
		add(BorderLayout.SOUTH, control_panel);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource().equals(connectButton)) {
			/*WaitDialog dialog = new WaitDialog(this, "Authentification",
					"Veuillez patienter pendant l'authentification avec le serveur.");
			dialog.start();*/
			
			boolean cmd_auth = true;
			
			// liste des ips
			Session session = HibernateUtil.getSession();
			Transaction tx = session.beginTransaction();

			List<?> list = session.createCriteria(ServerCentral.class).list();
			ip_central = ((ServerCentral) list.get(0)).getServCentr_ip();

			list = session.createCriteria(ServerAuth.class).list();
			ip_auth = ((ServerAuth) list.get(0)).getAuth_ip_adress();

			list = session.createCriteria(ServerWeb.class).list();
			ip_web = ((ServerWeb) list.get(0)).getWebserv_ip();

			tx.commit();
			
			ArrayList<String> msg_list = new ArrayList<String>();
			msg_list.add(KrakenClientMsg.KRAKEN_CLIENT.makeCommand());
			msg_list.add(KrakenClientMsg.ASK_FOR_TOKEN.makeCommand(
					" "+ip_central
					+ "  "+ip_auth
					+ "  "+REQUEST_TYPE
					+ "  0"
					+ "  "+ip_site
					+ "  "+ip_cam));
			msg_list.add(KrakenClientMsg.END_CLIENT.makeCommand());

			KrakenClient auth_client = new KrakenClient(msg_list, ip_web);
			auth_client.connect();
			auth_client.communicate();

			String answer = auth_client.getFinalAnswer();
			if(answer.equalsIgnoreCase(KrakenServerMsg.END_SERVER.toString())) {
				System.out.println("\nGénération de jeton réussie\nOn se connecte au serveur en SSL !");
				// test authentification auprès du serveur site via le jeton
				String jeton = StringUtils.bytesToString(auth_client.getSaved_data());

				ArrayList<String> msg_list_cmd = new ArrayList<>();
				msg_list_cmd.add(KrakenClientMsg.KRAKEN_SSL_CLIENT.makeCommand());
				msg_list_cmd.add(KrakenClientMsg.ASK_FOR_STREAMING.makeCommand(" "+jeton));
				msg_list_cmd.add(KrakenClientMsg.READY_FOR_STREAMING.makeCommand(" cmd"));
				msg_list_cmd.add(KrakenClientMsg.END_SSL_CLIENT.makeCommand());

				cmd_client = new KrakenSSLClient(msg_list_cmd, ip_site, 0);
				cmd_client.setStream_state(1);

				NetworkThread cmd_network_thead = new NetworkThread(cmd_client);
				cmd_thread = new Thread(cmd_network_thead);
				cmd_thread.start();
				
				while(cmd_client.getAuth() != 1) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e1) {
						e1.printStackTrace();
					}
					
					if(cmd_client.getFinalAnswer() != null) {
						//System.out.println(cmd_client.getFinalAnswer());
						if(cmd_client.getFinalAnswer().split("  ")[0].equals(KrakenServerMsg.ERROR.toString())) {
							System.out.println("error");
							cmd_auth = false;
							break;
						}
					}
				}
				
				if(cmd_auth) {
					System.out.println("\nAuthentification réussie\n"+
							"On se connecte au serveur en SSL pour recevoir le streaming!");
					// test authentification auprès du serveur site via le jeton
					String jeton_video = StringUtils.bytesToString(cmd_client.getSaved_data());
	
					ArrayList<String> msg_list_vid = new ArrayList<>();
					msg_list_vid.add(KrakenClientMsg.KRAKEN_SSL_CLIENT.makeCommand());
					msg_list_vid.add(KrakenClientMsg.SEND_TOKEN_FOR_VIDEO.makeCommand(" "+jeton_video));
					msg_list_vid.add(KrakenClientMsg.READY_FOR_STREAMING.makeCommand(" vid"));
					//msg_list_vid.add(KrakenClientMsg.END_SSL_CLIENT.makeCommand());
	
					vid_client = new KrakenSSLClient(msg_list_vid, ip_site, 1);
					vid_client.setStream_state(1);
	
					NetworkThread vid_network_thead = new NetworkThread(vid_client);
					vid_thread = new Thread(vid_network_thead);
					vid_thread.start();
	
					authenticated = true;
					display_panel.setCmd_client(cmd_client);
					display_panel.setVid_client(vid_client);
					stopButton.setEnabled(true);
					pauseButton.setEnabled(true);
					connectButton.setEnabled(false);
	
					display_thread = new Thread(((StreamPanel) display_panel));
					display_thread.start();
					revalidate();
					System.out.println("Streaming started!");
				}

			}
			else {
				// la génération du jeton a échouée
				JOptionPane.showMessageDialog(this,
						"L'authentification avec le serveur distant à échouée.",
						"Erreur d'authentification",
						JOptionPane.ERROR_MESSAGE);
				
				cmd_client.sendMessage(KrakenClientMsg.END_SSL_CLIENT.toString());
			}
			//dialog.dispose();
		}
		else if(e.getSource().equals(playButton)) {
			if(authenticated) {
				display_panel.play();
				pauseButton.setEnabled(true);
				playButton.setEnabled(false);
				/*msg_list = new ArrayList<String>();
				msg_list.add(KrakenClientMsg.KRAKEN_SSL_CLIENT.makeCommand());
				msg_list.add(KrakenClientMsg.PLAY_STREAM.makeCommand());
				msg_list.add(KrakenClientMsg.END_SSL_CLIENT.makeCommand());

				cmd_client.setMessages(msg_list);
				cmd_client.connect();
				cmd_client.communicate();*/

				// TODO recevoir la reponse
				/*try {
					display_panel.connect("localhost", 9999);
					display_thread = new Thread(((StreamPanel) display_panel));
					display_thread.start();
					revalidate();
				} catch (UnknownHostException e1) {
					e1.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}*/
			}
		}
		else if(e.getSource().equals(pauseButton)) {
			if(authenticated) {
				display_panel.pause();
				pauseButton.setEnabled(false);
				playButton.setEnabled(true);
			}
		}
		else if(e.getSource().equals(stopButton)) {
			if(authenticated) {
				display_panel.stop();
				pauseButton.setEnabled(false);
				playButton.setEnabled(false);
				stopButton.setEnabled(false);
				connectButton.setEnabled(true);
			}
		}
	}

	public void changeFPS(String text) {
		fps_count_label.setText(text);
	}

	public void changeLatency(String text) {
		latency_count_label.setText(text);
	}

	// setters

	public void setIp_central(String ip_central) { this.ip_central = ip_central; }
	public void setIp_auth(String ip_auth) { this.ip_auth = ip_auth; }
	public void setIp_site(String ip_site) { this.ip_site = ip_site; }
	public void setIp_cam(String ip_cam) { this.ip_cam = ip_cam; }

}
